<template>
  <div class="visual-tool" v-if="!initializing">
    <div class="visual-panel" v-if="currConfig">
      <div class="visual-panel-item" v-if="currConfig === 'style'">
        <div class="status-group">
          <div class="label">状态</div>
          <div class="button">
            <ac-icon
              iconId="018dca3b4707c4c43a2f"
              size="14"
              color="#bfbfbf"
              style="cursor: pointer"
              @click="addStyle"
            />
          </div>
        </div>
        <div v-if="(activatedNode.styleList || []).length > 1" class="status-box">
          <div
            class="status-item"
            v-for="style in activatedNode.styleList || []"
            :key="style.id"
          >
            <div class="label">
              <ac-icon
                v-if="style.id === currStyleId"
                iconId="018dca412c4e207388f7"
                size="14"
                style="cursor: pointer"
              />
              <ac-icon
                v-else
                iconId="018f68cc34330101d11d"
                size="14"
                style="cursor: pointer"
                @click="() => changeStyle(style.id)"
              />
            </div>
            <div class="content">
              <span v-if="style.name === '原始状态'">{{style.name}}</span>
              <el-input
                v-else
                v-model="style.name"
                size="small"
              />
            </div>
            <div
              v-if="style.name !== '原始状态'"
              class="button"
              style="margin-left: 8px;"
            >
              <ac-icon
                iconId="018dc9c3efd3a0502886"
                size="14"
                color="rgb(245,108,108)"
                style="cursor: pointer"
                title="删除"
                @click="() => deleteStyle(style.id)"
              />
            </div>
          </div>
        </div>
        <div class="style-box">
          <el-collapse v-model="collapseNames">
            <el-collapse-item
              v-for="(group, index) in styleList"
              :key="index"
              :title="group.name"
              :name="group.name"
            >
              <div
                v-for="(style, index) in group.children"
                :key="index"
                class="style-item"
              >
                <el-tooltip
                  v-if="style.description"
                  placement="left"
                  :content="style.description"
                  popper-class="padding-10-15"
                >
                  <span class="label">{{style.name}}：</span>
                </el-tooltip>
                <span v-else-if="style.name" class="label">{{style.name}}：</span>
                <span class="content">
                  <Component
                    :is="'ac-' + style.fieldType"
                    v-model="currStyle[style.fieldName]"
                    v-bind="cleanProp(style)"
                    size="small"
                  />
                </span>
              </div>
            </el-collapse-item>
          </el-collapse>
        </div>
      </div>
      <div class="visual-panel-item" v-if="currConfig === 'compStyle'">
        <div class="status-group">
          <div class="label">状态</div>
          <div class="button">
            <ac-icon
              iconId="018dca3b4707c4c43a2f"
              size="14"
              color="#bfbfbf"
              style="cursor: pointer"
              @click="addStyle"
            />
          </div>
        </div>
        <div v-if="(activatedNode.styleList || []).length > 1" class="status-box">
          <div
            v-for="(style, index) in activatedNode.styleList || []"
            :key="index"
            class="status-item"
          >
            <div class="label">
              <ac-icon
                v-if="style.id === currStyleId"
                iconId="018dca412c4e207388f7"
                size="14"
                style="cursor: pointer"
              />
              <ac-icon
                v-else
                iconId="018f68cc34330101d11d"
                size="14"
                style="cursor: pointer"
                @click="() => changeStyle(style.id)"
              />
            </div>
            <div class="content">
              <span v-if="style.name === '原始状态'">{{style.name}}</span>
              <el-input
                v-else
                v-model="style.name"
                size="small"
              />
            </div>
            <div
              v-if="style.name !== '原始状态'"
              class="button"
              style="margin-left: 8px;"
            >
              <ac-icon
                iconId="018dc9c3efd3a0502886"
                size="14"
                color="rgb(245,108,108)"
                style="cursor: pointer"
                title="删除"
                @click="() => deleteStyle(style.id)"
              />
            </div>
          </div>
        </div>
        <div class="style-box">
          <div class="style-item">
            <span class="label">组件名称：</span>
            <span class="content">
              <el-input size="small" v-model="activatedNode.name" />
            </span>
          </div>
          <div
            class="style-item"
            style="margin-bottom: 1px;"
          >
            <span class="label">
              <span>默认值</span>
              <span
                v-if="!currCompStyle.defaultType || currCompStyle.defaultType === 'input'"
                style="margin-left: 3px"
              ><ac-default-value-tips @change="(value) => currCompStyle.defaultValue = value"/></span>
              <span>：</span>
            </span>
            <div style="flex-grow: 1">
              <ac-select
                v-if="currCompStyle.defaultType === 'param'"
                v-model="currCompStyle.defaultValue"
                :options="inputParamOptions"
                title="默认值"
                size="small"
              />
              <ac-tree
                v-else-if="currCompStyle.defaultType === 'script'"
                v-model="currCompStyle.defaultValue"
                data-url="/system/scriptGroovy/queryTree"
                type-select="script"
                size="small"
              />
              <ac-input
                v-else
                v-model="currCompStyle.defaultValue"
                title="默认值"
                size="small"
              />
            </div>
            <div style="margin-left: 5px;flex-shrink: 0;width: 60px">
              <ac-select
                v-model="currCompStyle.defaultType"
                placeholder="请选择"
                :options="[
                  {key: 'input', value: '输入'},
                  {key: 'param', value: '参数'},
                  {key: 'script', value: '脚本'}
                ]"
                size="small"
              />
            </div>
          </div>
          <el-collapse v-model="collapseCompNames" v-if="compStyleList.length > 0">
            <el-collapse-item
              v-for="(group, index) in compStyleList"
              :key="index"
              :title="group.name"
              :name="group.name"
            >
              <div v-if="group.type !== 'group'" class="style-item">
                <span v-if="group.name" class="label">{{group.name}}：</span>
                <span class="content">
                  <Component
                    :is="'ac-' + group.fieldType"
                    v-model="currStyle[group.fieldName]"
                    v-bind="cleanProp(group)"
                    v-bind:fieldList="getFieldList()"
                    size="small"
                  />
                </span>
              </div>
              <div
                v-else
                v-for="(style, index) in group.children"
                :key="index"
                class="style-item"
              >
                <div
                  v-if="style.name"
                  class="label"
                >
                  <el-tooltip
                    v-if="style.description"
                    placement="left"
                    :content="style.description"
                    popper-class="padding-10-15"
                  >
                    <span class="label-name">{{style.name}}</span>
                  </el-tooltip>
                  <span v-if="!style.description" class="label-name">{{style.name}}</span>
                  <span
                    v-if="style.name === '默认值'
                      && (style.fieldType === 'input'
                        || style.fieldType === 'script-input')"
                    style="margin-left: 3px;"
                  >
                    <ac-default-value-tips />
                  </span>
                  <span>：</span>
                </div>
                <span class="content" :style="{marginLeft: style.name ? '0' : '10px'}">
                  <Component
                    :is="'ac-' + (typeof style.fieldType === 'function'
                      ? style.fieldType(currCompStyle) : style.fieldType)"
                    v-model="currCompStyle[style.fieldName]"
                    v-bind="cleanProp(style)"
                    v-bind:fieldList="getFieldList()"
                    size="small"
                  />
                </span>
              </div>
            </el-collapse-item>
          </el-collapse>
        </div>
      </div>
      <div class="visual-panel-item" v-show="currConfig === 'compData'">
        <comp-data />
      </div>
      <div class="visual-panel-item" v-if="currConfig === 'compEvent'">
        <comp-event @change="eventChange" />
      </div>
      <div class="visual-panel-item tree" v-if="currConfig === 'compTree'">
        <el-tree
          ref="treeRef"
          :data="[rootNode]"
          :props="treeProps"
          :expand-on-click-node="false"
          :current-node-key="activatedNode.id"
          :draggable="props.type === '大屏'"
          default-expand-all
          node-key="id"
          :allow-drag="allowDrag"
          @node-click="treeNodeClick"
          @node-drag-end="handleDragEnd"
        ></el-tree>
      </div>
      <div class="visual-panel-item tpl" v-if="currConfig === 'tpl'">
        <div class="tpl-box">
          <div class="tpl-item-wrapper" v-for="(item, index) in tplList" :key="index">
            <div class="tpl-item">
              <div class="tpl-item-name" v-if="item.edit">
                <el-input v-model="item.name" @change="savePageTpl(item)" @blur="item.edit = false" />
              </div>
              <div class="tpl-item-name border" v-else @dblclick="item.edit = true">{{item.name || '模板'}}</div>
              <div class="tpl-item-add">
                <ac-icon
                  iconId="018ece4f72d1bf69178b"
                  size="20"
                  color="#21D914FF"
                  style="cursor: pointer"
                  title="追加到当前节点"
                  @click="() => addTplToNode(item)"
                />
              </div>
              <div class="tpl-item-delete">
                <ac-icon
                  iconId="018dc9c3efd3a0502886"
                  size="16"
                  color="rgb(245,108,108)"
                  style="cursor: pointer"
                  title="删除"
                  @click="() => deleteTpl(item)"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="visual-panel-item" v-if="currConfig === 'comp'">
        <el-collapse v-model="compNames">
          <el-collapse-item
            v-for="(item, index) in compList"
            :key="index"
            :name="item.name"
            :title="item.name"
          >
            <div class="component-group-item">
              <vue-draggable
                v-model="item.children"
                item-key="type"
                class="component-box"
                :group="{name: 'nodeGroup', pull: 'clone', put: false}"
                :clone="cloneComponent"
                :sort="false"
                @end="onDragEnd"
              >
                <template #item="{ element }">
                  <div
                    class="component-item"
                    :title="element.name.length > 6 ? element.name : ''"
                  >
                    <el-tooltip
                      v-if="element.img"
                      effect="light"
                      :enterable="false"
                      popper-class="padding-10-15-center"
                    >
                      <template #content>
                        <ac-local-img :img="element.img" :width="150" :height="112" />
                      </template>
                      <div style="width: 100%">{{element.name }}</div>
                    </el-tooltip>
                    <span v-else>{{ element.name }}</span>
                  </div>
                </template>
              </vue-draggable>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>
    </div>
    <div class="visual-menu">
      <div title="保存" class="menu-item" @click="save">
        <ac-icon iconId="018ece4f68db3d9f13c1" color="#67C23A" size="20" />
      </div>
      <div title="另存为模板" class="menu-item" @click="saveTpl" v-if="props.type === '大屏' && props.showSaveType">
        <ac-icon iconId="018ece4f68db3d9f13c1" color="#0896CD" size="20" />
      </div>
      <div title="退出" class="menu-item" @click="quit">
        <ac-icon iconId="018ece4f732eee924b02" color="red" size="20" />
      </div>
      <div title="预览" class="menu-item" @click="preview">
        <ac-icon iconId="018dc9c3efed3042d4d3" color="#ddd" size="20" />
      </div>
      <div
        title="样式"
        :class="['menu-item', currConfig === 'style' ? 'is-active' : '']"
        @click="() => changeConfig('style')"
      >
        <ac-icon iconId="018ece4f712124866f78" color="#ddd" size="20" />
      </div>
      <div
        title="组件设置"
        :class="['menu-item', currConfig === 'compStyle' ? 'is-active' : '']"
        @click="() => changeConfig('compStyle')"
      >
        <ac-icon iconId="018ece4f775aa2fce122" color="#ddd" size="20" />
      </div>
      <div
        title="数据"
        :class="['menu-item', currConfig === 'compData' ? 'is-active' : '']"
        @click="() => changeConfig('compData')"
      >
        <ac-icon iconId="018ece4f721bb04985f7" color="#ddd" size="20" />
      </div>
      <div
        title="事件"
        :class="['menu-item', currConfig === 'compEvent' ? 'is-active' : '']"
        @click="() => changeConfig('compEvent')"
      >
        <ac-icon iconId="018ece4f70d7130088a7" color="#ddd" size="20" />
      </div>
      <div
        title="组件树"
        :class="['menu-item', currConfig === 'compTree' ? 'is-active' : '']"
        @click="() => changeConfig('compTree')"
      >
        <ac-icon iconId="018ece4f71bb880f77dc" color="#ddd" size="20" />
      </div>
      <div
        title="模板"
        :class="['menu-item', currConfig === 'tpl' ? 'is-active' : '']"
        @click="() => changeConfig('tpl')"
      >
        <ac-icon iconId="018ece4f7578ad8407e5" color="#ddd" size="20" />
      </div>
      <div
        title="组件"
        :class="['menu-item', currConfig === 'comp' ? 'is-active' : '']"
        @click="() => changeConfig('comp')"
      >
        <ac-icon iconId="018ece4f775aa2fce122" color="#ddd" size="20" />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, nextTick, computed, inject } from 'vue';
import vueDraggable from 'vuedraggable';
import tool from "@/utils/tool";
import { useAdminVisualCompStore } from '@/admin/visual/js/visual-comp';
import { commonStyle } from "./js/common.config";
import { components } from './js/component.config';
import visual from "@/visual/js/visual";
import CompEvent from "./comp-event.vue";
import CompData from "./comp-data.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import api from "@/http/api";

const props = defineProps({
  type: String,
  showSaveType: {
    type: Boolean,
    default: true
  },
  theme: {
    type: Object,
    default: () => ({fontColor: '#333'})
  }
});
const initializing = ref(true);
const compList = ref([]);
const emit = defineEmits(['preview', 'save', 'saveTpl', 'quit', 'change', 'activeNode']);
const visualComp = useAdminVisualCompStore();
const currStyleSeq = ref(1);
const currStyleId = ref('');
const currStyle = ref({});
const collapseNames = ref([]);
const currCompStyle = ref({});
const collapseCompNames = ref([]);
const currConfig = ref('style');
const rootNode = inject('rootNode');
const activatedNode = inject('activatedNode');
const nameIndex = inject('nameIndex');
const compConfigList = ref([]);
const compNames = ref([]);
const treeRef = ref();
const treeProps = {
  children: 'children',
  label: 'name',
};
const tplList = ref([]);
const pageParamList = inject("pageParamList");

const treeNodeClick = (node) => {
  if (node.builtin) return;
  emit('activeNode', node);
};

const changeConfig = (config) => {
  currConfig.value = config;
};

const addStyle = async() => {
  currStyleId.value = tool.uuids();
  currStyle.value = initStyle({});
  currCompStyle.value = await initCompStyle({});
  const style = {
    id: currStyleId.value,
    name: '状态' + currStyleSeq.value++,
    style: currStyle.value,
    compStyle: currCompStyle.value,
  };
  activatedNode.value.styleList.push(style);
  activatedNode.value.currStyle = currStyle.value;
  activatedNode.value.currCompStyle = currCompStyle.value;
};

const deleteStyle = (id) => {
  ElMessageBox.confirm("请确认是否删除？", "提示", { type: "warning" }).then(async() => {
    const index = activatedNode.value.styleList.findIndex(item => item.id === id);
    activatedNode.value.styleList.splice(index, 1);

    if (currStyle.value.id === id) {
      currStyleId.value = activatedNode.value.styleList[0].id;
      currStyle.value = initStyle(activatedNode.value.styleList[0].style);
      currCompStyle.value = await initCompStyle(activatedNode.value.styleList[0].compStyle);
      activatedNode.value.currStyle = currStyle.value;
      activatedNode.value.currCompStyle = currCompStyle.value;
    }
  }).catch(() => {});
};

const changeStyle = async(id) => {
  currStyleId.value = id;
  currStyle.value = initStyle((activatedNode.value.styleList.find(item => item.id === id) || {}).style);
  currCompStyle.value = await initCompStyle((activatedNode.value.styleList.find(item => item.id === id) || {}).compStyle);
  activatedNode.value.currStyle = currStyle.value;
  activatedNode.value.currCompStyle = currCompStyle.value;
};

const initStyle = (style) => {
  commonStyle.forEach(item => {
    if (item.type !== 'group' && item.fieldName && typeof style[item.fieldName] === 'undefined') {
      style[item.fieldName] = getValue(style[item.fieldName], item.default);
    }
    if (item.children && item.children.length > 0) {
      initStyleByDefault(style, item.children);
    }
  });

  return style;
};

const initStyleByDefault = (style, list) => {
  list.forEach(item => {
    if (item.type !== 'group' && item.fieldName && typeof style[item.fieldName] === 'undefined') {
      style[item.fieldName] = getValue(style[item.fieldName], item.default);
    }
    if (item.children && item.children.length > 0) {
      initStyleByDefault(style, item.children);
    }
  });
};

const initCompStyle = async(style) => {
  (tool.deepClone(await getCompStyle()) || []).forEach(item => {
    if (item.type !== 'group' && item.fieldName && typeof style[item.fieldName] === 'undefined') {
      style[item.fieldName] = getValue(style[item.fieldName], item.default);
    }
    if (item.children && item.children.length > 0) {
      initCompStyleByDefault(style, item.children);
    }
  });

  return style;
};

const initCompStyleByDefault = (style, list) => {
  list.forEach(item => {
    if (item.type !== 'group' && item.fieldName && typeof style[item.fieldName] === 'undefined') {
      style[item.fieldName] = getValue(style[item.fieldName], item.default);
    }
    if (item.children && item.children.length > 0) {
      initCompStyleByDefault(style, item.children);
    }
  });
};

const getValue = (...args) => {
  for (let item of args) {
    if (item === 0 || item) {
      return typeof item === 'string'
        ? item.replace(/{([^}]+)}/g, (_, key) => props.theme[key] ?? '')
        : item;
    }
  }
  return null;
};

const getFormItemOptions = () => {
  const options = [];
  tool.walkTree(rootNode.value, node => {
    if (node.id && node.formItem === '1') {
      options.push({key: node.id, value: node.name});
    }
  });
  return options;
};

const buildNameIndex = () => {
  const regex = new RegExp('-\\d+$');
  tool.walkTree(rootNode.value, node => {
    if (node.name && node.name.match(regex)) {
      const lastIndex = node.name.lastIndexOf('-');
      const name = node.name.substring(0, lastIndex);
      const maxIndex = parseInt(node.name.substring(lastIndex + 1));
      if (!nameIndex.value[name] || nameIndex.value[name] < maxIndex) {
        nameIndex.value[name] = maxIndex;
      }
    }
  });
};

const getNodeName = (name) => {
  if (!name) return '组件-01';

  if (name.endsWith('-')) {
    name = name.substr(0, name.length - 1);
  }

  if (!nameIndex.value[name]) {
    buildNameIndex();
  }

  if (!nameIndex.value[name]) {
    nameIndex.value[name] = 0;
  }

  let index = ++nameIndex.value[name];
  return name + '-' + (index < 10 ? '0' : '') + index;
};

const cleanProp = (data) => {
  const clone = tool.deepClone(data);
  const result = {};
  for (let p in clone) {
    if (p !== 'name'
        && p !== 'fieldName'
        && p !== 'fieldType'
        && p !== 'default'
        && p !== 'description'
        && p !== 'show') {
      if (typeof clone[p] === 'function') {
        result[p] = clone[p](currCompStyle.value);
      } else if (p === 'options' && clone[p] === 'formItemOptions') {
        result[p] = getFormItemOptions();
      } else {
        result[p] = clone[p];
      }
    }
  }
  return result;
};

const getFieldList = () => {
  const fieldList = activatedNode.value.compData?.fieldList || [];
  return fieldList.map(item => item.name).filter(item => item).join(',');
};

const tempNode = ref();
const cloneComponent = (comp) => {
  if (props.type === '大屏') {
    comp.position = 'absolute';
    comp.width = '600px';
    comp.height = '300px';
    comp.display = 'flex';
    comp['flex-direction'] = 'column';
    comp['justify-content'] = 'center';
    comp['align-items'] = 'center';
  }
  tempNode.value = visual.createNode(getNodeName(comp.name), comp);
  return tempNode.value;
};

const onDragEnd = (event) => {
  if (event.from !== event.to && tempNode.value) {
    emit('activeNode', tempNode.value);
    tempNode.value = null;
  }
};

const allowDrag = (draggingNode) => {
  return draggingNode.builtin !== true;
};

const handleDragEnd = (draggingNode) => {
  const nodeList = tool.getParentNodes(rootNode.value, draggingNode.data.id);
  if (nodeList && nodeList.length > 0) {
    nodeList[0].children.forEach((item, index) => {
      item.currStyle['z-index'] = index;
    });
  }
};

const preview = () => {
  emit('preview');
};

const save = () => {
  emit('save');
};

const saveTpl = () => {
  emit('saveTpl');
};

const quit = () => {
  emit('quit');
};

const init = async() => {
  if (!activatedNode.value) return;

  currStyleSeq.value = 1;
  for (let style of (activatedNode.value.styleList || [])) {
    const matches = style.name.match(/(\d+)$/);
    const index = parseInt(matches ? matches[1] : '0');
    if (index > currStyleSeq.value) {
      currStyleSeq.value = index;
    }
  }

  currStyleId.value = activatedNode.value
    && activatedNode.value.styleList
    && activatedNode.value.styleList[0].id || '';

  currStyle.value = initStyle(activatedNode.value
    && activatedNode.value.styleList
    && activatedNode.value.styleList[0].style || {});
  activatedNode.value.currStyle = currStyle.value;

  currCompStyle.value = await initCompStyle(activatedNode.value
    && activatedNode.value.styleList
    && activatedNode.value.styleList[0].compStyle || {});
  activatedNode.value.currCompStyle = currCompStyle.value;

  compNames.value = [];
  collapseNames.value = [];
  collapseCompNames.value = ['组件设置'];

  commonStyle.forEach(item => collapseNames.value.push(item.name));
  compList.value = components.filter(comp => !props.type || !comp.scene || comp.scene.includes(props.type));
  compList.value.forEach(item => {
    item.children = item.children.filter(comp => !props.type || !comp.scene || comp.scene.includes(props.type));
    compNames.value.push(item.name);
  });

  (await getCompStyle() || []).forEach(item => collapseCompNames.value.push(item.name));

  treeRef.value && treeRef.value.setCurrentKey(activatedNode.value.id);
};

const createCompStyle = (data, children) => {
  (children || []).forEach(item => {
    if (item.type && item.styleList) {
      const styleList = tool.deepClone(item.styleList)
      data[item.type] = styleList;
      if (item.defaultStyle) {
        tool.walkTree({children: styleList}, style => {
          if (style.fieldName && style.fieldName && item.defaultStyle[style.fieldName]) {
            style.default = item.defaultStyle[style.fieldName];
          }
        });
      }
    }
    createCompStyle(data, item.children);
  });
};

const styleList = computed(() => {
  const list = tool.deepClone(commonStyle);
  list.forEach(item => {
    if (item.children) {
      item.children = item.children.filter(item => !item.show || item.show(currStyle.value));
    }
  });
  return list;
});

const inputParamOptions = computed(() => {
  const options = [];
  (pageParamList.value || []).forEach(param => {
    options.push({key: param.id || '', value: '[全局参数].' + (param.name || '参数名')});
  });
  return options;
});

const getCompStyle = async() => {
  if (activatedNode.value.type) {
    if (!compConfigList.value[activatedNode.value.type]) {
      const comp = tool.deepClone(await visualComp.getVisualComp(activatedNode.value.type));
      compConfigList.value[activatedNode.value.type] = comp && comp.styleList || [];
    }
    return tool.deepClone(compConfigList.value[activatedNode.value.type]) || [];
  } else {
    return [];
  }
};

const addTplToNode = (data) => {
  if (activatedNode.value && activatedNode.value.children && data.json) {
    activatedNode.value.children.push(createNodeFromTpl(JSON.parse(data.json)));
  } else {
    ElMessage.error("请选择要添加的容器！");
  }
};

const savePageTpl = (data) => {
  api.post("/system/pageVisualTemplate/save", data).then(res => {
    if (res.code === '1') {
      data.edit = false;
      ElMessage.success("修改模板名称成功！");
      loadVisualTpl();
    }
  });
};

const deleteTpl = (data) => {
  ElMessageBox.confirm("请确认是否删除？", "提示", { type: "warning" }).then(async() => {
    api.post("/system/pageVisualTemplate/delete", data).then(res => {
      if (res.code === '1') {
        ElMessage.success("删除模板成功！");
        loadVisualTpl();
      }
    });
  }).catch(() => {});
};

const createNodeFromTpl = (tpl) => {
  resetId(tpl);
  tool.walkTree(tpl, item => {
    resetId(item);
  });
  return tpl;
};

const resetId = (node) => {
  if (node.id) {
    node.id = tool.uuids();
  }
  if (node.name) {
    const lastIndex = node.name.lastIndexOf('-');
    const name = node.name.substring(0, lastIndex);
    node.name = getNodeName(name);
  }
  (node.styleList || []).forEach(style => {
    style.id = tool.uuids();
  });
};

const loadVisualTpl = () => {
  api.post("/system/pageVisualTemplate/queryList", {type: '普通'}).then(res => {
    tplList.value = res && res.data || [];
  });
};

const eventChange = () => {
  emit('change');
};

watch(() => activatedNode.value.id, () => {
  init();
}, {immediate: true});

watch(() => currStyle.value, (style) => {
  activatedNode.value.currStyle = style;
  if (activatedNode.value.currCompStyle) {
    activatedNode.value.currCompStyle.refresh = !activatedNode.value.currCompStyle.refresh;
  }
  emit('change');
}, {deep: true});

const compStyleList = ref();
watch(() => currCompStyle.value, async(compStyle) => {
  const list = tool.deepClone(await getCompStyle() || []).filter(item => item.name !== '应用设置');
  list.forEach(item => {
    item.name = item.name === '电脑端设置' ? '组件设置' : item.name;
    item.children = (item.children || []).filter(item => !item.show || item.show(compStyle));
  });
  compStyleList.value = list;
  activatedNode.value.currCompStyle = compStyle;
  emit('change');
}, {deep: true});

onMounted(() => {
  initializing.value = true;
  createCompStyle(compConfigList.value, components);
  loadVisualTpl();
  nextTick(() => initializing.value = false);
});

defineExpose({ loadVisualTpl });
</script>

<style scoped lang="scss">
.visual-tool {
  height: 100%;
  display: flex;
  flex-direction: row;
  .visual-panel {
    height: 100%;
    width: 1px;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    background: #555555;
    .visual-panel-item {
      height: 1px;
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      overflow: auto;
      :deep(.el-text) {
        color: white;
      }
    }
    :deep(.el-collapse) {
      --el-collapse-border-color: unset!important;
      --el-collapse-header-height: 35px;
      --el-collapse-header-bg-color: #333!important;
      --el-collapse-header-text-color: white;
      --el-collapse-content-bg-color: #555555;
      --el-collapse-content-text-color: white;
      border-bottom: 1px solid #666666;
      border-top: none!important;
      .el-collapse-item {
        border-bottom: 1px solid #444;
      }
      .el-collapse-item:last-child {
        border-bottom: none;
      }
      .el-collapse-item__header {
        text-indent: 20px;
      }
      .el-collapse-item__content {
        padding-bottom: 0!important;
      }
    }
    :deep(.el-tree) {
      padding: 8px;
      background: #555555;
      color: #dcdcdc;
      width: 100%;
      --el-tree-node-content-height: 26px;
      --el-tree-node-hover-bg-color: #333;
      --el-tree-text-color: #dcdcdc;
      --el-tree-expand-icon-color: #dcdcdc;
    }
    :deep(.el-tree-node.is-current)>.el-tree-node__content {
      background: #333!important;
    }
    :deep(.el-input) {
      --el-input-text-color: #dcdcdc;
      --el-input-border-color: none;
      --el-input-bg-color: #333;
      --el-input-hover-border-color: none;
      --el-disabled-bg-color: #333;
      --el-disabled-border-color: none;
      --el-text-color-placeholder: #666666;
      .el-input__inner, .el-textarea__inner, .el-checkbox, .el-checkbox__label {
        color: #cccccc !important;
      }
    }
    :deep(.el-input).is-disabled {
      --el-input-text-color: #dcdcdc;
      --el-input-border-color: none;
      --el-input-bg-color: #333;
      --el-input-hover-border-color: none;
      --el-disabled-bg-color: #333;
      --el-disabled-border-color: none;
      -webkit-text-fill-color: #cccccc;
      .el-input__inner, .el-textarea__inner, .el-checkbox, .el-checkbox__label {
        color: #cccccc !important;
        -webkit-text-fill-color: #cccccc !important;
      }
    }
    :deep(.el-textarea) .el-textarea__inner {
      background: #333!important;
      box-shadow: none;
      color: #dcdcdc!important;
    }
    :deep(.el-select) .el-input__inner {
      border: none!important;
    }
    :deep(.el-select) {
      .el-select__wrapper {
        background: #333;
        color: #dcdcdc!important;
        box-shadow: none;
      }
      .el-input__inner {
        border-color: #666;
      }
      .el-select__placeholder {
        border: none!important;
        color: #dcdcdc!important;
      }
    }
    :deep(.el-checkbox) {
      margin-right: 15px;
      .el-checkbox__label {
        color: #dcdcdc!important;
      }
      .el-checkbox__input .el-checkbox__inner {
        background: rgb(180, 180, 180);
        border-color: rgb(180, 180, 180);
      }
      .el-checkbox__input.is-checked .el-checkbox__inner {
        background: #333;
        border-color: #333;
      }
    }
    :deep(.el-radio) {
      margin-right: 15px;
      .el-radio__label {
        color: #dcdcdc!important;
      }
      .el-radio__input .el-radio__inner {
        background: rgb(180, 180, 180);
        border-color: rgb(180, 180, 180);
      }
      .el-radio__input.is-checked .el-radio__inner {
        background: #333;
        border-color: #333;
      }
    }
    :deep(.ac-icon-select) {
      border-color: #333;
      background: #333;
      color: #dcdcdc;
    }
    :deep(.el-switch) .el-switch__core {
      background: #b4b4b4;
      border-color: #b4b4b4;
    }
    :deep(.el-switch).is-checked .el-switch__core {
      background: #333;
      border-color: #333;
    }
    :deep(.el-input-number--small .el-input__wrapper) {
      padding-left: 5px!important;
    }
    :deep(.el-collapse-item__header) {
      box-sizing: border-box;
    }
    .status-group {
      flex-shrink: 0;
      height: 35px;
      text-indent: 20px;
      background: #333333;
      color: white;
      display: flex;
      flex-direction: row;
      align-items: center;
      border-bottom: 1px solid #444;
      .label {
        flex-shrink: 0;
        display: flex;
        flex-direction: row;
        align-items: center;
      }
      .button {
        flex-grow: 1;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: end;
        margin-right: 8px;
      }
    }
    .status-box {
      padding: 2px 4px;
    }
    .status-item {
      color: white;
      display: flex;
      flex-direction: row;
      align-items: center;
      padding: 2px 4px;

      .label {
        flex-shrink: 0;
        text-align: right;
        display: flex;
        flex-direction: row;
        align-items: center;
        color: #dcdcdc;
      }
      .content {
        flex-grow: 1;
        margin-left: 8px;
        display: flex;
        flex-direction: row;
        align-items: center;
        font-size: 13px;
        :deep(.el-input) {
          .el-input__inner {
            color: #dcdcdc!important;
            font-size: 12px;
          }
        }
      }
      .button {
        display: flex;
        flex-direction: row;
        align-items: center;
      }
    }
    .style-box {
      flex-grow: 1;
      overflow: auto;
      :deep(.el-collapse-item__wrap) {
        padding: 2px 0;
        background: #555555!important;
      }
    }
    .style-item {
      color: white;
      display: flex;
      flex-direction: row;
      padding: 2px 3px;
      .label {
        width: 92px;
        height: 24px;
        flex-shrink: 0;
        color: #dcdcdc;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-end;
        font-size: 13px;
        :deep(.label-name) {
          width: 90px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          text-align: right;
          display: block;
        }
      }
      .content {
        flex-grow: 1;
        display: flex;
        flex-direction: row;
        align-items: center;
      }
      :deep(.el-radio-button) {
        --el-radio-button-checked-bg-color: #555;
        --el-radio-button-checked-text-color: #dcdcdc;
        --el-radio-button-checked-border-color: #333;
        --el-radio-button-disabled-checked-fill: #333;
      }
      :deep(.el-radio-button) .el-radio-button__inner {
        color: #dcdcdc;
        background: #555555;
        border-right: 1px solid #333;
        border-top: 1px solid #333;
        border-bottom: 1px solid #333;
        padding: 5px 6px;
      }
      :deep(.el-radio-button:first-child) .el-radio-button__inner {
        border-left: 1px solid #333;
      }
      :deep(.el-radio-button).is-active .el-radio-button__inner {
        background: #333!important;
      }
    }
    .component-group {
      margin: 10px 0;
      height: 1px;
      flex-grow: 1;
      overflow-y: scroll;
      :deep(.el-collapse-item__content) {
        margin-bottom: 0!important;
        padding-bottom: 10px!important;
      }
    }
    .component-group-item {
      display: flex;
      flex-direction: column;
    }
    .component-box {
      display: grid;
      grid-template-columns: repeat(auto-fill, 145px);
      grid-gap: 5px 8px;
      justify-content: center;
      align-items: center;
      overflow-y: auto;
      padding: 5px 0;
      .component-item {
        background: rgb(66, 66, 66);
        padding: 0 12px;
        height: 32px;
        line-height: 32px;
        width: 120px;
        border: 1px solid #333;
        border-radius: 5px;
        color: #dcdcdc;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .component-item:hover {
        cursor: move;
        border: 1px dashed #ccc;
        background: rgb(51,51,51);
      }
    }
  }
  .visual-menu {
    padding: 10px 0;
    width: 50px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    background: rgb(66, 66, 66);
    .menu-item {
      padding: 5px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      cursor: pointer;
      margin-bottom: 10px;
    }

    .menu-item.is-active {
      border-radius: 5px;
      background: rgb(121, 121, 121);
    }

    .menu-item:hover {
      border-radius: 5px;
      background: rgb(121, 121, 121);
    }
  }
  :deep(.dark-drawer-box) {
    background: #555555;
    .el-drawer__body {
      padding: 0;
      background: rgb(85, 85, 85)!important;
    }
    .el-drawer__footer {
      border-top: 1px solid rgb(51, 51, 51)!important;
      padding: 8px;
      background: rgb(85, 85, 85)!important;
    }
  }
  .tpl-box {
    padding: 8px;
    .tpl-item {
      display: flex;
      flex-direction: row;
      align-items: center;
      margin-bottom: 8px;
      .tpl-item-name {
        width: 1px;
        flex-grow: 1;
        &.border {
          height: 30px;
          border: 1px solid #050505;
          border-radius: 5px;
          display: flex;
          flex-direction: row;
          align-items: center;
          color: #c0c0c0;
          text-indent: 10px;
        }
      }
      .tpl-item-add, .tpl-item-delete {
        margin-left: 5px;
      }
    }
  }
}
</style>